home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / dbg / ds5000.md / dbgMain.c < prev    next >
C/C++ Source or Header  |  1991-08-09  |  32KB  |  1,246 lines

  1. /* dbgMain.c -
  2.  *
  3.  *    This contains the routines which read and execute commands from kdbx.
  4.  *
  5.  *    Copyright (C) 1989 Digital Equipment Corporation.
  6.  *    Permission to use, copy, modify, and distribute this software and
  7.  *    its documentation for any purpose and without fee is hereby granted,
  8.  *    provided that the above copyright notice appears in all copies.  
  9.  *    Digital Equipment Corporation makes no representations about the
  10.  *    suitability of this software for any purpose.  It is provided "as is"
  11.  *    without express or implied warranty.
  12.  */
  13.  
  14. #ifndef lint
  15. static char rcsid[] = "$Header: /sprite/src/kernel/dbg/ds3100.md/RCS/dbgMain.c,v 9.9 91/08/09 16:27:37 jhh Exp $ SPRITE (Berkeley)";
  16. #endif not lint
  17.  
  18. #include <sprite.h>
  19. #include <dbg.h>
  20. #include <dbgInt.h>
  21. #include <mach.h>
  22. #include <machConst.h>
  23. #include <proc.h>
  24. #include <vm.h>
  25. #include <vmMach.h>
  26. #include <machMon.h>
  27. #include <net.h>
  28. #include <netEther.h>
  29. #include <netInet.h>
  30. #include <dev.h>
  31. #include <sys.h>
  32. #include <sync.h>
  33. #include <main.h>
  34.  
  35. #ifdef KDBX
  36. #include <user/signal.h>
  37. #endif
  38.  
  39. static unsigned sstepInst;            /* The instruction that was
  40.                          * replaced when we tried to
  41.                          * single step. */
  42. Boolean dbg_InDebugger = FALSE;            /* TRUE if are currently in
  43.                          * the debug command loop. */
  44. Boolean    dbg_BeingDebugged = FALSE;        /* TRUE if are under control
  45.                          * of kdbx.*/
  46. Boolean    dbg_Rs232Debug = FALSE;            /* TRUE if are using the RS232
  47.                          * line to debug, FALSE if are
  48.                          * using the network. */
  49. Boolean    dbg_UsingNetwork = FALSE;        /* TRUE if the debugger is
  50.                          * using the network interface*/
  51. static char requestBuffer[DBG_MAX_REQUEST_SIZE];/* Buffer to receive request
  52.                          * into. */
  53. static int    requestOffset;            /* Offset in buffer where next
  54.                          * bytes should be read from.*/
  55. static char replyBuffer[DBG_MAX_REPLY_SIZE + 2];/* Buffer to hold reply. */
  56. static int    replyOffset = 0;        /* Offset in buffer where next
  57.                          * bytes in reply should go. */
  58. static unsigned int    curMsgNum;        /* The current message that
  59.                          * is being processed. */
  60. int    dbgTraceLevel = 0;            /* The debugger tracing
  61.                          * level. */
  62.  
  63. /*
  64.  * Number of times to poll before timing out and resending (about 2 seconds).
  65.  */
  66. int    dbgTimeout = 15000;
  67.  
  68. /*
  69.  * Information about the latest packet received.
  70.  */
  71. Boolean            dbgGotPacket;    
  72. int            dbgPacketLength;
  73. Net_InetAddress        dbgMyIPAddr;
  74. Net_InetAddress        dbgSrcIPAddr;
  75. Net_InetAddress        dbgSrcPort;
  76. Net_EtherHdr        dbgEtherHdr;
  77. Net_ScatterGather    dbgGather;
  78. Net_Interface        *dbgInterPtr = (Net_Interface *) NIL;
  79.  
  80. /*
  81.  * Size of debugging packet header and data.
  82.  */
  83. #define    PACKET_HDR_SIZE (sizeof(Net_EtherHdr) + Dbg_PacketHdrSize() + 4 + 2)
  84. #define PACKET_DATA_SIZE (DBG_MAX_REPLY_SIZE - PACKET_HDR_SIZE)
  85.  
  86.  
  87. /*
  88.  * Strings which describe each of the opcodes that kdbx can send us.
  89.  */
  90. static char *opcodeNames[] = DBG_OPCODE_NAMES ;
  91.  
  92. /*
  93.  * Strings which describe the different exceptions that can occur.
  94. */
  95. static char *exceptionNames[] = DBG_EXCEPTION_NAMES;
  96.  
  97. /*
  98.  * Whether syslog should remain diverted on continue or not.
  99.  */
  100. static Boolean    syslogDiverted = FALSE;
  101.  
  102. /*
  103.  * Declare global variables.
  104.  */
  105. int        dbgTermReason;
  106. int        dbgInDebugger;
  107. int        dbgIntPending;
  108. Boolean        dbgPanic;
  109. Boolean        dbg_UsingSyslog = FALSE;
  110. Boolean        dbgCanUseSyslog = TRUE;
  111. int        dbgMaxStackAddr;
  112. #ifdef KDBX
  113. int        dbgSignal;
  114. static Boolean    useKdbx = FALSE;
  115. #endif
  116. /*
  117.  * Trap causes (same numbering as in ptrace.h).
  118.  */
  119. #define CAUSE_SINGLE    4
  120. #define CAUSE_BREAK    5
  121.  
  122. /*
  123.  * Trap instruction.
  124.  */
  125. #define SSTEP_INST    (MACH_SSTEP_VAL | 0xd)
  126.  
  127. /* 
  128.  * Forward declarations:
  129.  */
  130.  
  131. static char *    TranslateOpcode _ARGS_((int opcode));
  132. static char *    TranslateException _ARGS_((int exception));
  133. static Boolean    ReadRequest _ARGS_((Boolean timeout));
  134. static void    SendReply _ARGS_((int dataSize));
  135. static void    DebugToRegState _ARGS_((Mach_DebugState *debugPtr, 
  136.             Mach_RegState *regPtr));
  137. static void    RegStateToDebug _ARGS_((Mach_RegState *regPtr, 
  138.             Mach_DebugState *debugPtr)); 
  139.  
  140. #ifdef KDBX
  141. static int    sigMap[] = {
  142.     /* MACH_EXC_INT         */        SIGILL,
  143.     /* MACH_EXC_TLB_MOD     */        SIGSEGV,
  144.     /* MACH_EXC_TLB_LD_MISS     */        SIGSEGV, 
  145.     /* MACH_EXC_TLB_ST_MISS     */        SIGSEGV, 
  146.     /* MACH_EXC_ADDR_ERR_LD     */         SIGBUS,
  147.     /* MACH_EXC_ADDR_ERR_ST     */        SIGBUS,
  148.     /* MACH_EXC_BUS_ERR_IFETCH     */        SIGBUS,
  149.     /* MACH_EXC_BUS_ERR_LD_ST     */        SIGBUS,
  150.     /* MACH_EXC_SYSCALL     */        SIGSYS,
  151.     /* MACH_EXC_BREAK         */        SIGTRAP,
  152.     /* MACH_EXC_RES_INST     */        SIGILL,
  153.     /* MACH_EXC_COP_UNUSABLE     */        SIGILL, 
  154.     /* MACH_EXC_OVFLOW         */        SIGILL,
  155. };
  156.  
  157. #endif
  158.  
  159.  
  160. /*
  161.  * ----------------------------------------------------------------------------
  162.  *
  163.  * Dbg_InRange --
  164.  *
  165.  *     Return true if the given address is a valid kernel address and false
  166.  *     otherwise.
  167.  *
  168.  * Results:
  169.  *     True if the given address is a valid kernel address and false
  170.  *     otherwise.
  171.  *
  172.  * Side effects:
  173.  *     None.
  174.  *
  175.  * ----------------------------------------------------------------------------
  176.  */
  177. /*ARGSUSED*/
  178. Boolean Dbg_InRange(addr, numBytes, writeable) 
  179.     unsigned     int addr;     /* Beginning address to check. */
  180.     int        numBytes;     /* Number of bytes to check. */
  181.     Boolean    writeable;    /* TRUE => address must be writeable. */
  182. {
  183.     int            firstPage;
  184.     int            lastPage;
  185.  
  186.     firstPage = addr >> VMMACH_PAGE_SHIFT;
  187.     lastPage = (addr + numBytes - 1) >> VMMACH_PAGE_SHIFT;
  188.     if (firstPage != lastPage) {
  189.     Mach_MonPrintf("Dbg_InRange: Object spans pages\n");
  190.     return(FALSE);
  191.     }
  192.     return(VmMach_MakeDebugAccessible(addr));
  193. }
  194.  
  195.  
  196. /*
  197.  * ----------------------------------------------------------------------------
  198.  *
  199.  * TranslateOpcode --
  200.  *
  201.  *     Return the string which describes the given opcode.
  202.  *
  203.  * Results:
  204.  *     Pointer to the string which describes the given opcode.
  205.  *
  206.  * Side effects:
  207.  *     None.
  208.  *
  209.  * ----------------------------------------------------------------------------
  210.  */
  211. static char *
  212. TranslateOpcode(opcode)
  213.     int opcode;        /* The opcode which is to be translated. */
  214. {
  215.     int index;
  216.  
  217.     index = (int) opcode;
  218.     if (index < 0 || index >= sizeof(opcodeNames) / 4) {
  219.         index = 0;
  220.     }
  221.  
  222.     return(opcodeNames[index]);
  223. }
  224.  
  225.  
  226. /*
  227.  * ----------------------------------------------------------------------------
  228.  *
  229.  * TranslateException --
  230.  *
  231.  *     Return the string that describes the given exception.
  232.  *
  233.  * Results:
  234.  *     Pointer to string which describes the given exception.
  235.  *
  236.  * Side effects:
  237.  *     None.
  238.  *
  239.  * ----------------------------------------------------------------------------
  240.  */
  241. static char *
  242. TranslateException(exception)
  243.     int exception;        /* The exception which is to be translated. */
  244. {
  245.  
  246.     if (exception < 0 || exception > MACH_EXC_OVFLOW) {
  247.         return("Unknown");
  248.     } else {
  249.         return(exceptionNames[exception]);
  250.     }
  251. }
  252.  
  253.  
  254. /*
  255.  * ----------------------------------------------------------------------------
  256.  *
  257.  * Dbg_Init --
  258.  *
  259.  *     Initialize the debugger.
  260.  *
  261.  * Results:
  262.  *     None.
  263.  *
  264.  * Side effects:
  265.  *     Global variables are initialized.
  266.  *
  267.  * ----------------------------------------------------------------------------
  268.  */
  269. void
  270. Dbg_Init()
  271. {
  272. #ifdef KDBX
  273.     extern void DbgDbxInit();
  274. #endif
  275.     dbgInDebugger = 0;
  276.     dbgIntPending = 0;
  277.     dbgPanic = FALSE;
  278.     dbg_BeingDebugged = FALSE;
  279. #ifdef KDBX
  280.     DbgDbxInit();
  281. #endif
  282. }
  283.  
  284.  
  285.  
  286. /*
  287.  * ----------------------------------------------------------------------------
  288.  *
  289.  * Dbg_InputPacket --
  290.  *
  291.  *     See if the current packet is for us.
  292.  *
  293.  * Results:
  294.  *     None.
  295.  *
  296.  * Side effects:
  297.  *     dbgGotPacket is set to true if we got a packet that we liked.
  298.  *
  299.  * ----------------------------------------------------------------------------
  300.  */
  301. void
  302. Dbg_InputPacket(interPtr, packetPtr, packetLength)
  303.     Net_Interface    *interPtr;
  304.     Address        packetPtr;
  305.     int            packetLength;
  306. {
  307.     Net_EtherHdr    *etherHdrPtr;
  308.     Net_IPHeader    *ipPtr;
  309.     Address        dataPtr;
  310.     int            dataLength;
  311.  
  312.     if (interPtr->netType != NET_NETWORK_ETHER) {
  313.     Mach_MonPrintf("Got a debugger packet on non-ethernet interface %s\n",
  314.         interPtr->name);
  315.     return;
  316.     }
  317.     etherHdrPtr = (Net_EtherHdr *)packetPtr;
  318.  
  319.     if (dbgTraceLevel >= 5) {
  320.     if ((unsigned char)etherHdrPtr->destination.byte1 != 0xff) {
  321.         Mach_MonPrintf("Size=%d S: %x:%x:%x:%x:%x:%x D: %x:%x:%x:%x:%x:%x T=%x\n",
  322.             packetLength,
  323.             (unsigned char)etherHdrPtr->source.byte1,
  324.             (unsigned char)etherHdrPtr->source.byte2,
  325.             (unsigned char)etherHdrPtr->source.byte3,
  326.             (unsigned char)etherHdrPtr->source.byte4,
  327.             (unsigned char)etherHdrPtr->source.byte5,
  328.             (unsigned char)etherHdrPtr->source.byte6,
  329.             (unsigned char)etherHdrPtr->destination.byte1,
  330.             (unsigned char)etherHdrPtr->destination.byte2,
  331.             (unsigned char)etherHdrPtr->destination.byte3,
  332.             (unsigned char)etherHdrPtr->destination.byte4,
  333.             (unsigned char)etherHdrPtr->destination.byte5,
  334.             (unsigned char)etherHdrPtr->destination.byte6,
  335.             Net_NetToHostShort(etherHdrPtr->type));
  336.     }
  337.     }
  338.  
  339.     if (Net_NetToHostShort(etherHdrPtr->type) != NET_ETHER_IP) {
  340.     if (dbgTraceLevel >= 5) {
  341.         Mach_MonPrintf("Non-IP (Type=0x%x) ",
  342.             Net_NetToHostShort(etherHdrPtr->type));
  343.     }
  344.     return;
  345.     }
  346.     if (dbgGotPacket) {
  347.     if (dbgTraceLevel >= 4) {
  348.         Mach_MonPrintf("Dbg_InputPacket: already have a packet\n");
  349.     }
  350.     return;
  351.     }
  352.     if (dbgTraceLevel >= 4) {
  353.     Mach_MonPrintf("Validating packet\n");
  354.     }
  355.     { 
  356.     static char alignedBuffer[NET_ETHER_MAX_BYTES];
  357.         /*
  358.      * Make sure the packet starts on a 32-bit boundry so that we can
  359.      * use structures for describe the data.
  360.      */
  361.     if ( (unsigned int) (packetPtr + sizeof(Net_EtherHdr)) & 0x3 ) {
  362.           bcopy (packetPtr + sizeof(Net_EtherHdr), alignedBuffer,
  363.                 packetLength - sizeof(Net_EtherHdr));
  364.           packetPtr = alignedBuffer;
  365.     } else {
  366.           packetPtr = packetPtr + sizeof(Net_EtherHdr);
  367.     }
  368.  
  369.     if (Dbg_ValidatePacket(packetLength - sizeof(Net_EtherHdr),
  370.                    (Net_IPHeader *)(packetPtr),
  371.                    &dataLength, &dataPtr,
  372.                    &dbgMyIPAddr, &dbgSrcIPAddr, &dbgSrcPort)) {
  373.         if (dbgTraceLevel >= 4) {
  374.         Mach_MonPrintf("Got a packet: length=%d\n", dataLength);
  375.         }
  376.         bcopy((Address)etherHdrPtr, (Address)&dbgEtherHdr,
  377.             sizeof(Net_EtherHdr));
  378.         dbgGotPacket = TRUE;
  379.         bcopy(dataPtr, requestBuffer, dataLength);
  380. #ifdef KDBX
  381.         DbgDbxStoreRequest(dataLength, requestBuffer);
  382. #endif
  383.         /*
  384.          * Set the interface we are using. 
  385.          */
  386.         dbgInterPtr = interPtr;
  387.         return;
  388.     }
  389.     }
  390. }
  391.  
  392.  
  393. /*
  394.  * ----------------------------------------------------------------------------
  395.  *
  396.  * ReadRequest --
  397.  *
  398.  *     Read the next request from kdbx.
  399.  *
  400.  * Results:
  401.  *     None.
  402.  *
  403.  * Side effects:
  404.  *     TRUE if didn't time out.
  405.  *
  406.  * ----------------------------------------------------------------------------
  407.  */
  408. static Boolean
  409. ReadRequest(timeout)
  410.     Boolean    timeout;    /* TRUE if should timeout after waiting a 
  411.                  * while. */
  412. {
  413.     int            timeOutCounter;
  414.     Net_Interface    *interPtr;
  415.     int            i;
  416.  
  417.     dbgGotPacket = FALSE;
  418.     timeOutCounter = dbgTimeout;
  419.     do {
  420.     /*
  421.      * Listen on all the interfaces. The debugger is relatively
  422.      * stateless so its easiest to just listen on them all.
  423.      */
  424.     for (i = 0; ; i++) {
  425.         interPtr = Net_NextInterface(TRUE, &i);
  426.         if (interPtr == (Net_Interface *) NIL) {
  427.         break;
  428.         }
  429.         Net_RecvPoll(interPtr);
  430.         if (dbgGotPacket) {
  431.         break;
  432.         }
  433.     }
  434.     if (timeout) {
  435.         timeOutCounter--;
  436.     }
  437.     } while(!dbgGotPacket && timeOutCounter != 0);
  438.     if (dbgGotPacket) {
  439.     replyOffset = PACKET_HDR_SIZE;
  440.     requestOffset = 4;
  441.     curMsgNum = *(unsigned int *)(requestBuffer);
  442. #ifdef KDBX
  443.     if (curMsgNum > 0x40000000) {
  444.         useKdbx = FALSE;
  445.     } else {
  446.         useKdbx = TRUE;
  447.     }
  448. #endif
  449.     if (dbgTraceLevel >= 4) {
  450.         Mach_MonPrintf("MsgNum = %d\n", curMsgNum);
  451.     }
  452.     }
  453.  
  454.     return(dbgGotPacket);
  455. }
  456.  
  457. /*
  458.  * ----------------------------------------------------------------------------
  459.  *
  460.  * GetRequestBytes --
  461.  *
  462.  *     Get the next numBytes bytes from the current request.
  463.  *
  464.  * Results:
  465.  *     None.
  466.  *
  467.  * Side effects:
  468.  *     None.
  469.  *
  470.  * ----------------------------------------------------------------------------
  471.  */
  472. static void
  473. GetRequestBytes(numBytes, dest)
  474.     int        numBytes;
  475.     Address    dest;
  476. {
  477.     bcopy(requestBuffer + requestOffset, dest, numBytes);
  478.     requestOffset += numBytes;
  479. }
  480.  
  481.  
  482. /*
  483.  * ----------------------------------------------------------------------------
  484.  *
  485.  * PutReplyBytes --
  486.  *
  487.  *     Put the given bytes into the reply buffer.
  488.  *
  489.  * Results:
  490.  *     None.
  491.  *
  492.  * Side effects:
  493.  *     None.
  494.  *
  495.  * ----------------------------------------------------------------------------
  496.  */
  497. static void
  498. PutReplyBytes(numBytes, src)
  499.     int        numBytes;
  500.     Address    src;
  501. {
  502.     if (replyOffset + numBytes > DBG_MAX_REPLY_SIZE) {
  503.     Mach_MonPrintf("PutReplyBytes: Buffer overflow\n");
  504.     numBytes = DBG_MAX_REPLY_SIZE - replyOffset;
  505.     }
  506.     bcopy(src, &replyBuffer[replyOffset], numBytes);
  507.     replyOffset += numBytes;
  508. }
  509.  
  510.  
  511. /*
  512.  * ----------------------------------------------------------------------------
  513.  *
  514.  * SendReply --
  515.  *
  516.  *     Send a reply to kdbx.
  517.  *
  518.  * Results:
  519.  *     None.
  520.  *
  521.  * Side effects:
  522.  *     None.
  523.  *
  524.  * ----------------------------------------------------------------------------
  525.  */
  526. static void
  527. SendReply(dataSize)
  528.     int    dataSize;
  529. {
  530.     Net_EtherHdr        *etherHdrPtr;
  531.  
  532.     if (dbgTraceLevel >= 4) {
  533.     Mach_MonPrintf("Sending reply\n");
  534.     }
  535.  
  536.     etherHdrPtr = (Net_EtherHdr *) (replyBuffer+2);
  537.     etherHdrPtr->source = dbgEtherHdr.destination;
  538.     etherHdrPtr->destination = dbgEtherHdr.source;
  539.     etherHdrPtr->type = dbgEtherHdr.type;
  540.     dbgGather.bufAddr = replyBuffer + sizeof(Net_EtherHdr)+2;
  541.     dbgGather.length = replyOffset - sizeof(Net_EtherHdr)-2;
  542.     dbgGather.mutexPtr = (Sync_Semaphore *) NIL;
  543.     bcopy((char *)&curMsgNum,(char *)(replyBuffer + PACKET_HDR_SIZE - 4),4);
  544.     Dbg_FormatPacket(dbgMyIPAddr, dbgSrcIPAddr, dbgSrcPort,
  545.          replyOffset - sizeof(Net_EtherHdr) - Dbg_PacketHdrSize()-2,
  546.          replyBuffer + sizeof(Net_EtherHdr) + 2);
  547.     Net_RawOutput(dbgInterPtr, etherHdrPtr, &dbgGather, 1);
  548.     if (dbgTraceLevel >= 4) {
  549.     Mach_MonPrintf("Sent reply\n");
  550.     }
  551. }
  552.  
  553.  
  554. /*
  555.  * Should we sync the disks on entering the debugger?
  556.  */
  557.  
  558. Boolean dbgSyncDisks = TRUE;
  559.  
  560. extern Mach_DebugState    mach_DebugState;
  561.  
  562. /*
  563.  * Place where the TLB is dumped when the kernel enters the debugger.
  564.  */
  565. unsigned dbgTLB[VMMACH_NUM_TLB_ENTRIES][2];
  566.  
  567. static Mach_DebugState    *debugStatePtr;
  568.  
  569.  
  570. /*
  571.  * ----------------------------------------------------------------------------
  572.  *
  573.  * Dbg_Main --
  574.  *
  575.  *     The main debugger loop.  This will read commands from the network
  576.  *     and call the proper routine to execute them.
  577.  *
  578.  * Results:
  579.  *     None.
  580.  *
  581.  * Side effects:
  582.  *     None.
  583.  *
  584.  * ----------------------------------------------------------------------------
  585.  */
  586. unsigned
  587. Dbg_Main()
  588. {
  589.     unsigned    cause;
  590.     Boolean          done;        /* Boolean to tell us whether to leave
  591.                      * the main debugger loop */
  592.     Dbg_Opcode          opcode;            /* The operation that was requested */
  593.                     /* Process table entry that we switched
  594.                      * stacks to. */
  595.     Proc_ControlBlock    *procPtr = (Proc_ControlBlock *) NIL;
  596.     Boolean        atInterruptLevel;/* TRUE if we were entered from an
  597.                       * interrupt handler. */
  598.     extern int Mach_SwitchPoint();
  599. #ifdef NOTDEF
  600. /*
  601.  * This code causes machines to "pop out" of the debugger.
  602.  */
  603.     if (!dbg_BeingDebugged && dbgSyncDisks) {
  604.     /*
  605.      * Try to sync the disks if we aren't at interrupt level.  If we
  606.      * are don't bother because we'll just hang waiting for interrupts.
  607.      * Of course I could force interrupts to be enabled but I'm not sure
  608.      * if that's a great idea.
  609.      */
  610.     if (mach_NumDisableIntrsPtr[0] == 0 &&
  611.         !mach_AtInterruptLevel) {
  612.         Mach_EnableIntr();
  613.         Sys_SyncDisks(MACH_OTHER_TRAP_TYPE);
  614.         Mach_DisableIntr();
  615.     }
  616.     }
  617. #endif NOTDEF
  618.  
  619.     dbg_InDebugger = TRUE;
  620.  
  621.     debugStatePtr = &mach_DebugState;
  622.  
  623.     if (dbgTraceLevel >= 1) {
  624.     unsigned int    *sp;
  625.     extern int etext;
  626.     
  627.     Mach_MonPrintf("\nCause=%x SR=%x excPC=%x SP=%x BVA=%x\n", 
  628.                mach_DebugState.causeReg, mach_DebugState.statusReg, 
  629.                mach_DebugState.excPC, mach_DebugState.regs[SP],
  630.                mach_DebugState.badVaddr);
  631.     Mach_MonPrintf("Stack:\n");
  632.     for (sp = (unsigned *)mach_DebugState.regs[SP]; 
  633.          sp < (unsigned *)0x80030000; 
  634.          sp++) {
  635.         if ((*sp < (unsigned int)&etext) && (*sp >= (unsigned)0x80030000)) {
  636.         Mach_MonPrintf("%x\n", *sp);
  637.         }
  638.     }
  639.     }
  640.  
  641.     atInterruptLevel = mach_AtInterruptLevel;
  642.     mach_AtInterruptLevel = TRUE;
  643.  
  644.     /*
  645.      * Force system log output to the console.
  646.      */
  647.     if (!syslogDiverted) {
  648.     Dev_SyslogDebug(TRUE);
  649.     }
  650.  
  651.     /*
  652.      * We want to inform the user what caused the problem.  However we only
  653.      * tell him if: 1) we are debugging the debugger; 2) we are not under 
  654.      * debugger control (i.e. we don't want to inform the user on every trace 
  655.      * trap), 3) we got something besides a trace trap or a breakpoint trap
  656.      * exception.
  657.      */
  658.     cause = (mach_DebugState.causeReg & MACH_CR_EXC_CODE) >> 
  659.                         MACH_CR_EXC_CODE_SHIFT;
  660.     if (dbgPanic) {
  661.     dbgPanic = FALSE;
  662.     mach_DebugState.excPC = mach_DebugState.regs[RA];
  663.     }
  664.  
  665.     if (dbgTraceLevel >= 1 || !dbg_BeingDebugged || 
  666.         cause != MACH_EXC_BREAK) {
  667.     (void)Dev_VidEnable(TRUE); /* unblank the screen */
  668.     printf("Entering debugger with a %s exception at PC 0x%x\r\n",
  669.            TranslateException((int)cause),
  670.            mach_DebugState.excPC);
  671.     }
  672. #ifdef KDBX
  673.     if ((cause >= 0) && (cause < MACH_EXC_MAX)) {
  674.     dbgSignal = sigMap[cause];
  675.     } else {
  676.     dbgSignal = SIGILL;
  677.     }
  678. #endif
  679.     if (cause == MACH_EXC_BREAK) {
  680.     unsigned        *pc;
  681.  
  682.     if (mach_DebugState.causeReg & MACH_CR_BR_DELAY) {
  683.         pc = (unsigned *)(mach_DebugState.excPC + 4);
  684.     } else {
  685.         pc = (unsigned *)mach_DebugState.excPC;
  686.     }
  687.     if (dbgTraceLevel >= 1) {
  688.         Mach_MonPrintf("break inst: %x\n", *pc);
  689.     }
  690.     if ((*pc & MACH_BREAK_CODE_FIELD) == MACH_SSTEP_VAL) {
  691.         if (dbgTraceLevel >= 1) {
  692.         Mach_MonPrintf("sstep\n");
  693.         }
  694.         mach_DebugState.trapCause = CAUSE_SINGLE;
  695.         if (dbgTraceLevel >= 1) {
  696.         Mach_MonPrintf("sstep (%x) = %x\n", pc, sstepInst);
  697.         }
  698.         Mach_FlushCode((Address)pc, 4);
  699.         *pc = sstepInst;
  700.         Mach_EmptyWriteBuffer();
  701.     } else {
  702.         mach_DebugState.trapCause = CAUSE_BREAK;
  703.     }
  704.     }
  705.  
  706.     dbg_UsingNetwork = TRUE;
  707.  
  708.     if (dbg_BeingDebugged) {
  709.         unsigned        char    ch;
  710.     int    timeout = 5;
  711.         ch = 0;
  712. #ifdef KDBX
  713.     if (useKdbx) {
  714.         Dbg_DbxMain();
  715.         goto there;
  716.     }
  717. #endif
  718.         PutReplyBytes(1, (Address)&ch);
  719.         SendReply();
  720.         do {
  721.             if (ReadRequest(TRUE)) {
  722.                 GetRequestBytes(4, (Address)&opcode);
  723.         if (opcode != DBG_CONTINUE) {
  724.             break;
  725.         } else {
  726.             PutReplyBytes(4, (Address) &opcode);
  727.             SendReply();
  728.             continue;
  729.         }
  730.             }
  731.             /*
  732.              * We can only timeout if we are using network debugging.
  733.              */
  734.         Net_RawOutput(dbgInterPtr, (Address) replyBuffer, 
  735.             &dbgGather, 1);
  736.             if (dbgTraceLevel >= 5) {
  737.                 Mach_MonPrintf("DBG: Timeout\n");
  738.             }
  739.             Mach_MonPrintf("TI ");
  740.         } while (timeout-- > 0);
  741.     } else {
  742.         (void) ReadRequest(FALSE);
  743. #ifdef KDBX
  744.     if (useKdbx) {
  745.         Dbg_DbxMain();
  746.         goto there;
  747.     }
  748. #endif
  749.         GetRequestBytes(4, (Address)&opcode);
  750.     }
  751.  
  752.     Vm_MachDumpTLB(dbgTLB);
  753.  
  754.     done = FALSE;
  755.     while (!done) {
  756.     if (dbgTraceLevel >= 2) {
  757.         Mach_MonPrintf("Request: (%d) %s\n", opcode, TranslateOpcode(opcode));
  758.     }
  759.     switch (opcode) {
  760.  
  761.         /*
  762.          * The client wants to read some data from us ...
  763.          */
  764.  
  765.         case DBG_GET_STOP_INFO: {
  766.         StopInfo    stopInfo;
  767.         stopInfo.codeStart = (int)mach_CodeStart;
  768.         if (procPtr != (Proc_ControlBlock *) NIL &&
  769.             procPtr->machStatePtr != (Mach_State *)NIL) {
  770.             stopInfo.regs = procPtr->machStatePtr->switchRegState;
  771.             /*
  772.              * The pc isn't stored in switchRegState, but we know
  773.              * that we had to be in Mach_ContextSwitch.  Also,
  774.              * when the context switch is done the status register
  775.              * and a magic number are pushed on the stack. We
  776.              * need to adjust the sp so that the debugger doesn't
  777.              * get confused by them. 
  778.              */
  779.             stopInfo.regs.pc = (Address) 
  780.                 ((char *) Mach_ContextSwitch + 16);
  781.             stopInfo.regs.regs[SP] += 8;
  782.         } else {
  783.             DebugToRegState(&mach_DebugState, &stopInfo.regs);
  784.         }
  785.         stopInfo.trapType = cause;
  786.         PutReplyBytes(sizeof(stopInfo), (Address)&stopInfo);
  787.         SendReply();
  788.         break;
  789.         }
  790.         case DBG_READ_ALL_REGS: {
  791.         Mach_RegState    regState;
  792.         if (procPtr != (Proc_ControlBlock *) NIL &&
  793.             procPtr->machStatePtr != (Mach_State *)NIL) {
  794.             regState = procPtr->machStatePtr->switchRegState;
  795.             regState.pc = (Address) (Mach_SwitchPoint);
  796.             regState.pc = (Address) 
  797.                 ((char *) Mach_ContextSwitch + 16);
  798.             regState.regs[SP] += 8;
  799.         } else {
  800.             DebugToRegState(&mach_DebugState, ®State);
  801.         }
  802.         PutReplyBytes(sizeof(regState), (Address) ®State);
  803.         SendReply();
  804.         }
  805. #if 0
  806.         case DBG_GET_DUMP_BOUNDS: {
  807.         Dbg_DumpBounds bounds;
  808.         extern unsigned int end;
  809.         bounds.pageSize = vm_PageSize;
  810.         bounds.stackSize = mach_KernStackSize;
  811.         bounds.kernelCodeStart = (unsigned int) mach_KernStart;
  812.         bounds.kernelCodeSize  = 
  813.             (unsigned int) (((Address)(&end)) - mach_KernStart);
  814.         bounds.kernelDataStart    = ((unsigned int)(&end));
  815.         bounds.kernelDataSize    = (unsigned int) 
  816.                 (vmMemEnd - ((Address)(&end)));
  817.         bounds.kernelStacksStart = (unsigned int)vmStackBaseAddr;
  818.         bounds.kernelStacksSize = (unsigned int) 
  819.                 (vmStackEndAddr - vmStackBaseAddr);
  820.         bounds.fileCacheStart    = (unsigned int)vmBlockCacheBaseAddr;
  821.         bounds.fileCacheSize    = (unsigned int) (vmBlockCacheEndAddr - 
  822.                         vmBlockCacheBaseAddr);
  823.  
  824.         PutReplyBytes(sizeof(bounds), (char *)&bounds);
  825.         SendReply();
  826.         break;
  827.         }
  828. #endif
  829.         case DBG_GET_VERSION_STRING: {
  830.         char    *version;
  831.  
  832.         version = SpriteVersion();
  833.         PutReplyBytes(strlen(version) + 1, version);
  834.         SendReply();
  835.         break;
  836.         }
  837.         case DBG_INST_READ:
  838.         case DBG_DATA_READ: {
  839.         Dbg_ReadMem    readMem;
  840.         int        status;
  841.  
  842.         GetRequestBytes(sizeof(readMem), (Address) &readMem); 
  843.         if (dbgTraceLevel >= 2) {
  844.             Mach_MonPrintf("Addr=%x Numbytes=%d ",
  845.                 readMem.address, readMem.numBytes);
  846.         }
  847.         if (Dbg_InRange(readMem.address, readMem.numBytes, FALSE)) {
  848.             status = 1;
  849.             PutReplyBytes(sizeof(status), (Address)&status);
  850.             PutReplyBytes(readMem.numBytes, (Address)readMem.address);
  851.         } else {
  852.             if (dbgTraceLevel >= 2) {
  853.             Mach_MonPrintf("FAILURE ");
  854.             }
  855.             status = 0;
  856.             PutReplyBytes(sizeof(status), (Address)&status);
  857.         }
  858.         SendReply();
  859.         break;
  860.         }
  861.         case DBG_SET_PID: {
  862.         Proc_PID    pid;
  863.  
  864.         GetRequestBytes(sizeof(pid), (Address) &pid);
  865.          {
  866.             int    dummy;
  867.  
  868.             PutReplyBytes(4, (Address) &dummy);
  869.             SendReply();
  870.         }
  871.         if (dbgTraceLevel >= 2) {
  872.             Mach_MonPrintf("pid %x ", pid);
  873.         }
  874.         if (pid == 0) {
  875.             procPtr = (Proc_ControlBlock *) NIL;
  876.         } else {
  877.             procPtr = Proc_GetPCB(pid);
  878.             if (procPtr == (Proc_ControlBlock *) NIL ||
  879.                 procPtr == (Proc_ControlBlock *) 0 ||
  880.             procPtr->state == PROC_UNUSED ||
  881.                 procPtr->state == PROC_DEAD ||
  882.             procPtr->state == PROC_NEW) {
  883.             Mach_MonPrintf("Can't backtrace stack for process %x\n",
  884.                     pid);
  885.             procPtr = (Proc_ControlBlock *) NIL;
  886.             }
  887.         }
  888.         break;
  889.         }
  890.         case DBG_REBOOT: {
  891.         int    stringLength;
  892.         char    rebootString[100];
  893.         /*
  894.          * For a reboot command first read the size of the string and
  895.          * then the string itself.
  896.          */
  897.         GetRequestBytes(sizeof(int), (Address)&stringLength);
  898.         if (stringLength != 0) {
  899.             GetRequestBytes(stringLength, (Address)rebootString);
  900.         }
  901.         rebootString[stringLength] = '\0';
  902.          {
  903.             int    dummy;
  904.  
  905.             PutReplyBytes(4, (Address) &dummy);
  906.             SendReply();
  907.         }
  908.         Mach_MonReboot(rebootString);
  909.         }
  910.         case DBG_INST_WRITE:
  911.         case DBG_DATA_WRITE: {
  912.         Dbg_WriteMem        writeMem;
  913.         unsigned    char    ch;
  914.         /*
  915.          * For an instruction or a data write we first have to find out 
  916.          * which address to write to and how many bytes to write.  Next
  917.          * we have to make sure that the address is valid.  If it is
  918.          * then we read the data and write it to the given address.  If
  919.          * not we just report an error to kdbx.
  920.          */
  921.         GetRequestBytes(2 * sizeof(int), (Address) &writeMem);
  922.         if (dbgTraceLevel >= 2) {
  923.             Mach_MonPrintf("Addr=%x Numbytes=%d ",
  924.                 writeMem.address, writeMem.numBytes);
  925.         }
  926.         if (Dbg_InRange((unsigned int) writeMem.address,
  927.                 writeMem.numBytes, opcode == DBG_DATA_WRITE)) {
  928.             GetRequestBytes(writeMem.numBytes,
  929.                     (Address) writeMem.address);
  930.             if (opcode == DBG_INST_WRITE) {
  931.             Mach_FlushCode((Address)writeMem.address, 
  932.                 writeMem.numBytes);
  933.             Mach_EmptyWriteBuffer();
  934.             }
  935.             ch = 1;
  936.         } else {
  937.             char    buf[100];
  938.  
  939.             if (dbgTraceLevel >= 2) {
  940.             Mach_MonPrintf("FAILURE ");
  941.             }
  942.             GetRequestBytes(writeMem.numBytes, buf);
  943.             ch = 0;
  944.         }
  945.         PutReplyBytes(1, (char *) &ch);
  946.         SendReply();
  947.  
  948.         break;
  949.         }
  950.         case DBG_WRITE_REG: {                
  951.         Mach_RegState    regState;
  952.         Dbg_WriteReg    writeReg;
  953.  
  954.         /*
  955.          * First find out which register is being written and
  956.          * then read the value.
  957.          */
  958.         GetRequestBytes(sizeof(writeReg), (Address)&writeReg);
  959.          {
  960.             int    dummy;
  961.  
  962.             PutReplyBytes(4, (Address) &dummy);
  963.             SendReply();
  964.         }
  965.         if (dbgTraceLevel >= 2) {
  966.             Mach_MonPrintf("register %d data %x ", writeReg.regNum, 
  967.                 writeReg.regVal);
  968.         }
  969.         if (procPtr != (Proc_ControlBlock *) NIL &&
  970.             procPtr->machStatePtr != (Mach_State *)NIL) {
  971.             ((int *) 
  972.             &procPtr->machStatePtr->switchRegState)[(writeReg.regNum)] 
  973.             = writeReg.regVal;
  974.         } else {
  975.             DebugToRegState(&mach_DebugState, ®State);
  976.             ((int *) ®State)[(writeReg.regNum)] = writeReg.regVal;
  977.             RegStateToDebug(®State, &mach_DebugState);
  978.         }
  979.         }
  980.         case DBG_DIVERT_SYSLOG: 
  981.         GetRequestBytes(sizeof(Boolean), (Address)&syslogDiverted);
  982.          {
  983.             int    dummy;
  984.  
  985.             PutReplyBytes(4, (Address) &dummy);
  986.             SendReply();
  987.         }
  988.         break;
  989.         case DBG_BEGIN_CALL: {
  990.         /*
  991.          * We are beginning a call command.  Fix up the stack
  992.          * so that we will be able to continue.  We will put
  993.          * it back when we are done.
  994.          */
  995.         int    dummy;
  996.         if (dbgCanUseSyslog) {
  997.             dbg_UsingSyslog = TRUE;
  998.         }
  999.  
  1000.         PutReplyBytes(4, (Address) &dummy);
  1001.         SendReply();
  1002.  
  1003.         break;
  1004.         }
  1005.         case DBG_END_CALL: {
  1006.         char    *buffer;
  1007.         int    *firstIndexPtr;
  1008.         int    *lastIndexPtr;
  1009.         int    bufSize;
  1010.         int    length;
  1011.         /*
  1012.          * Dump the syslog buffer.
  1013.          */
  1014.         Dev_SyslogReturnBuffer(&buffer, &firstIndexPtr,
  1015.                        &lastIndexPtr, &bufSize);
  1016.         if (*firstIndexPtr == -1) {
  1017.             length = 0;
  1018.             PutReplyBytes(4, (Address) &length);
  1019.             dbg_UsingSyslog = FALSE;
  1020.         } else if (*firstIndexPtr <= *lastIndexPtr) {
  1021.             length = *lastIndexPtr - *firstIndexPtr + 1;
  1022.             if (length + 4 > PACKET_DATA_SIZE) {
  1023.             length = PACKET_DATA_SIZE - 4;
  1024.             }
  1025.             PutReplyBytes(4, (Address) &length);
  1026.             PutReplyBytes(length,
  1027.                   (Address)&buffer[*firstIndexPtr]);
  1028.             *firstIndexPtr += length;
  1029.             if (*firstIndexPtr > *lastIndexPtr) {
  1030.             *firstIndexPtr = *lastIndexPtr = -1;
  1031.             }
  1032.         } else {
  1033.             length = bufSize - *firstIndexPtr;
  1034.             if (length + 4 > PACKET_DATA_SIZE) {
  1035.             length = PACKET_DATA_SIZE - 4;
  1036.             }
  1037.             PutReplyBytes(4, (Address) &length);
  1038.             PutReplyBytes(length,
  1039.                   (Address)buffer[*firstIndexPtr]);
  1040.             *firstIndexPtr += length;
  1041.             if (*firstIndexPtr == bufSize) {
  1042.             *firstIndexPtr = 0;
  1043.             }
  1044.         }
  1045.         SendReply();
  1046.         break;
  1047.         }
  1048.         case DBG_CALL_FUNCTION: {
  1049.         Dbg_CallFunc        callFunc;
  1050.         int            returnVal;
  1051.         static int        argBuf[128];
  1052.         GetRequestBytes(2 * sizeof(int), (Address) &callFunc);
  1053.         if (dbgTraceLevel >= 2) {
  1054.             Mach_MonPrintf("Addr=%x Numbytes=%d ",
  1055.                 callFunc.address, callFunc.numBytes);
  1056.         }
  1057.         if ((callFunc.numBytes >= 0 && callFunc.numBytes < 128) &&
  1058.              Dbg_InRange((unsigned int) callFunc.address,4,FALSE)) {
  1059.             GetRequestBytes(callFunc.numBytes,(Address) argBuf);
  1060.             returnVal = (* ((int (*)()) callFunc.address))(argBuf[0],
  1061.             argBuf[1],argBuf[2],argBuf[3],argBuf[4],argBuf[5],argBuf[6],
  1062.             argBuf[7],argBuf[8],argBuf[9]);
  1063.         } else {
  1064.  
  1065.             if (dbgTraceLevel >= 2) {
  1066.             Mach_MonPrintf("FAILURE ");
  1067.             }
  1068.             GetRequestBytes(callFunc.numBytes,(Address)argBuf);
  1069.             returnVal = -1;
  1070.         }
  1071.         PutReplyBytes(4, (char *) &returnVal);
  1072.         SendReply();
  1073.  
  1074.         break;
  1075.         }
  1076.         case DBG_CONTINUE: {
  1077.         /*
  1078.          * The client wants to continue execution.
  1079.          */
  1080.         int    foo;
  1081.         GetRequestBytes(sizeof(int), 
  1082.                 (Address) &foo);
  1083.         if (dbgTraceLevel >= 2) {
  1084.             Mach_MonPrintf("Continuing from pc %x ",debugStatePtr->excPC);
  1085.         }
  1086.         {
  1087.             int    dummy;
  1088.  
  1089.             PutReplyBytes(4, (Address) &dummy);
  1090.             SendReply();
  1091.         }
  1092.  
  1093.         dbg_BeingDebugged = TRUE;
  1094.         done = TRUE;
  1095.         break;
  1096.         }
  1097.         case DBG_SINGLESTEP: {
  1098.         /*
  1099.          * The client wants to single step.
  1100.          */
  1101.         unsigned        *pc;
  1102.         int            status;
  1103.         int            dummy;
  1104.  
  1105.         GetRequestBytes(sizeof(int),  (Address) &dummy);
  1106.         pc = DbgGetDestPC((Address)(debugStatePtr->excPC));
  1107.         if (dbgTraceLevel >= 1) {
  1108.             Mach_MonPrintf("Single-step PC=%x\n", pc);
  1109.         }
  1110.         if (!Dbg_InRange((unsigned int)pc, 4, TRUE)) {
  1111.             Mach_MonPrintf("Bad SSTEP PC\n");
  1112.             status = 0;
  1113.         } else {
  1114.             sstepInst = *pc;
  1115.             Mach_FlushCode((Address)pc, 4);
  1116.             *pc = SSTEP_INST;
  1117.             Mach_EmptyWriteBuffer();
  1118.             dbg_BeingDebugged = TRUE;
  1119.             done = TRUE;
  1120.             status = 1;
  1121.         }
  1122.         PutReplyBytes(sizeof(status), (Address) &status);
  1123.         SendReply();
  1124.         break;
  1125.         }
  1126.         case DBG_DETACH:
  1127.         /*
  1128.          * The debugger has terminated and wants to let us go about our
  1129.          * business.
  1130.          */
  1131.         if (dbgTraceLevel >= 2) {
  1132.             Mach_MonPrintf("Detaching at pc %x ", debugStatePtr->excPC);
  1133.         }
  1134.             {
  1135.             int    dummy;
  1136.  
  1137.             PutReplyBytes(4, (Address) &dummy);
  1138.             SendReply();
  1139.         }
  1140.  
  1141.         dbg_BeingDebugged = FALSE;
  1142.         done = TRUE;
  1143.         printf("Sprite is now detached from the debugger\r\n");
  1144.         break;
  1145.         case DBG_UNKNOWN:
  1146.         Mach_MonPrintf("debugger: unrecognized request\n");
  1147.         break;
  1148.     }
  1149.     if (dbgTraceLevel >= 2) {
  1150.         Mach_MonPrintf("\r\n");
  1151.     }
  1152.     if (!done) {
  1153.         (void)ReadRequest(FALSE);
  1154.         GetRequestBytes(4, (Address)&opcode);
  1155.     }
  1156.     }
  1157.  
  1158. #ifdef KDBX
  1159. there:
  1160. #endif
  1161.     /*
  1162.      * Don't force system log output to the console.
  1163.      */
  1164.     if (!syslogDiverted) {
  1165.     Dev_SyslogDebug(FALSE);
  1166.     }
  1167.  
  1168.     if (dbgTraceLevel >= 1) {
  1169.     Mach_MonPrintf("Returning to %x: %x\n", debugStatePtr->excPC, 
  1170.                 *(unsigned *)debugStatePtr->excPC);
  1171.     }
  1172.  
  1173.     mach_AtInterruptLevel = atInterruptLevel;
  1174.     dbg_UsingNetwork = FALSE;
  1175.     /*
  1176.      * Flush out the old TLB mapping.
  1177.      */
  1178.     VmMachWriteIndexedTLB(0, 0, 0);
  1179.  
  1180.     dbg_InDebugger = FALSE;
  1181.  
  1182.     return(debugStatePtr->excPC);
  1183. }
  1184.  
  1185. /*
  1186.  *----------------------------------------------------------------------
  1187.  *
  1188.  * DebugToRegState --
  1189.  *
  1190.  *    Converts a Mach_DebugState to Mach_RegState.
  1191.  *
  1192.  * Results:
  1193.  *    None.
  1194.  *
  1195.  * Side effects:
  1196.  *    None.
  1197.  *
  1198.  *----------------------------------------------------------------------
  1199.  */
  1200. static void
  1201. DebugToRegState(debugPtr, regPtr)
  1202.     Mach_DebugState    *debugPtr;
  1203.     Mach_RegState    *regPtr;
  1204. {
  1205.     regPtr->pc = (Address) debugPtr->excPC;
  1206.     bcopy((char *) debugPtr->regs, (char *) regPtr->regs, 
  1207.     MACH_NUM_GPRS * sizeof(int));
  1208.     bcopy((char *) debugPtr->fpRegs, (char *) regPtr->fpRegs, 
  1209.     MACH_NUM_FPRS * sizeof(int));
  1210.     regPtr->fpStatusReg = debugPtr->fpCSR;
  1211.     regPtr->mfhi = debugPtr->multHi;
  1212.     regPtr->mflo = debugPtr->multLo;
  1213. }
  1214.  
  1215. /*
  1216.  *----------------------------------------------------------------------
  1217.  *
  1218.  * RegStateToDebug --
  1219.  *
  1220.  *    Converts a Mach_RegState to Mach_DebugState.
  1221.  *
  1222.  * Results:
  1223.  *    None.
  1224.  *
  1225.  * Side effects:
  1226.  *    None.
  1227.  *
  1228.  *----------------------------------------------------------------------
  1229.  */
  1230.  
  1231. static void
  1232. RegStateToDebug(regPtr, debugPtr)
  1233.     Mach_RegState    *regPtr;
  1234.     Mach_DebugState    *debugPtr;
  1235. {
  1236.     debugPtr->excPC = (unsigned) regPtr->pc;
  1237.     bcopy((char *) regPtr->regs, (char *) debugPtr->regs, 
  1238.     MACH_NUM_GPRS * sizeof(int));
  1239.     bcopy((char *) regPtr->fpRegs, (char *) debugPtr->fpRegs, 
  1240.     MACH_NUM_FPRS * sizeof(int));
  1241.     debugPtr->fpCSR = regPtr->fpStatusReg;
  1242.     debugPtr->multHi = regPtr->mfhi;
  1243.     debugPtr->multLo = regPtr->mflo;
  1244. }
  1245.  
  1246.